package jk;

public class LrScanner {

    //action表
    static String[][] a;
    //goto表
    static int [][] b;
    //用于存储文法
    static String grammar[];
    //用于存储输入串
    static char input[];
    //指向当前判断位置的输入串指针
    static int inputCount=-1;
    //状态栈
    static int[] status = new int[20];
    //状态栈指针
    static int statusCount = 0;
    //符号栈
    static char[] symbol = new char[20];
    //符号栈指针
    static int symbolCount = -1;

    //主方法
    public static void main(String[] args){

        //通过自定义方法获取action表，goto表，和文法
        a = getString();
        b = getInt();
        grammar = getGrammar();
        //输入需要判断的句子
        input = "#i+i*i#".toCharArray();
        //调用方法开始循环入栈判断
        System.out.println(analyze());
    }

    //获取Action表
    public static String[][] getString(){
        String[][] a = new String[20][20];
        a[0][0]="s5";  a[0][3]="s4";
        a[1][1]="s6";  a[1][5]="acc";
        a[2][1]="r2";  a[2][2]="s7";  a[2][4]="r2";  a[2][5]="r2";
        a[3][1]="r4";  a[3][2]="r4";  a[3][4]="r4";  a[3][5]="r4";
        a[4][0]="s5";  a[4][3]="s4";
        a[5][1]="r6";  a[5][2]="r6";  a[5][4]="r6";  a[5][5]="r6";
        a[6][0]="s5";  a[6][3]="s4";
        a[7][0]="s5";  a[7][3]="s4";
        a[8][1]="s6";  a[8][4]="s11";
        a[9][1]="r1";  a[9][2]="s7";  a[9][4]="r1";  a[9][5]="r1";
        a[10][1]="r3";  a[10][2]="r3";  a[10][4]="r3";  a[10][5]="r3";
        a[11][1]="r5";  a[11][2]="r5";  a[11][4]="r5";  a[11][5]="r5";
        return a;
    }
    //获取goto表
    public static int[][] getInt(){
        int[][] b = new int[20][20];
        b[0][0]=1;  b[0][1]=2;  b[0][2]=3;
        b[4][0]=8;  b[4][1]=2;  b[4][2]=3;
        b[6][1]=9;  b[6][2]=3;
        b[7][2]=10;
        return b;
    }
    //获取文法
    public static String[] getGrammar(){
        String grammar[] = {" ","E->E+T","E->T","T->T*F","T->F","F->(E)","F->i"};
        return  grammar;
    }


    //进行循环入栈判断
    public static String analyze(){

        //判断是否以#开头，不是则返回错误
        if(input[0]!='#'){
            return "输入的不是句子";
        }

        //循环入栈查并表判断
        for(int i=0 ; i<input.length ; i++){
            //当循环到栈底时，就不再进行入栈操作
            if(i<input.length-1){
                symbolCount++;
                inputCount++;
                symbol[symbolCount] = input[inputCount];
            }
            //入栈后查表
            switch (action()){
                case 0:
                    return "输入的不是句子";
                case 1:
                    return "输入的是句子";
                case 2:
                    break;
            }
        }
        return "输入的不是句子";
    }

    //获取符号在Action表中的列号
    public static int judgeActionSymbol(){
        switch (input[inputCount+1]){
            case 'i':
                return 0;
            case '+':
                return 1;
            case '*':
                return 2;
            case '(':
                return 3;
            case ')':
                return 4;
            case '#':
                return 5;
            default:
                return 404;
        }

    }

    //获取符号在goto表中的列号
    public static int judgeGotoSymbol(){
        switch (symbol[statusCount]){
            case 'E':
                return 0;
            case 'T':
                return 1;
            case 'F':
                return 2;
            default:
                return 404;
        }
    }

    //查询Action表
    //返回结果 0代表错误 1代表成功且已到终态 2代表成功但未到终态
    public static int action(){
        //查表，并将值赋给action
        String action = a[status[statusCount]][judgeActionSymbol()];
        //每次查表，都将查询到的表的内容输出，以便调试
        System.out.println("action: a"+status[statusCount]+judgeActionSymbol()+" = "+action);
        //查询到 s 则进行入栈操作
        if(action.charAt(0)=='s'){
            statusCount++;
            status[statusCount]=Integer.parseInt(action.substring(1));
            return 2;
        }
        //查询到 r 则进行规约操作
        else if (action.charAt(0)=='r'){
            int del = grammar[Integer.parseInt(action.substring(1))].substring(3).length();
            for(int i=0;i<del;i++ ){
                symbolCount--;
                statusCount--;
            }
            symbolCount++;
            symbol[symbolCount] =  grammar[Integer.parseInt(action.substring(1))].charAt(0);
            //规约后查看goto表进行状态转换
            togoto();
            return 2;
        }
        //查询到acc表示成功
        else if(action.equals("acc")){
            return 1;
        }
        return 0;
    }

    //查询goto表
    public static void togoto(){
        //查询goto表 转换当前状态
        statusCount++;
        status[statusCount]=b[status[statusCount-1]][judgeGotoSymbol()];
        //每次查表，都将查询到的表的内容输出，以便调试
        System.out.println("goto: b"+status[statusCount-1]+judgeGotoSymbol()+" = "+ b[status[statusCount-1]][judgeGotoSymbol()]);
        //查询goto表转换状态后继续查询action表
        action();
    }
}
